package cloud.banson.emojilizer.home

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.compose.runtime.Composable
import cloud.banson.emojilizer.ui.home.HomeScreen
import cloud.banson.emojilizer.ui.theme.EmojilizerTheme

import android.os.Environment

import android.app.DownloadManager
import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.compose.material.rememberScaffoldState
import androidx.compose.runtime.rememberCoroutineScope
import cloud.banson.emojilizer.R
import cloud.banson.emojilizer.utils.TAG
import kotlinx.coroutines.*
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone.Companion.currentSystemDefault
import kotlinx.datetime.toLocalDateTime
import java.io.File
import java.lang.Exception


class HomeActivity : ComponentActivity() {

    /**
     * the model that will be used to hold data for this activity
     */
    private val viewModel by viewModels<HomeViewModel>()


    /**
     * registers for an ActivityResultContracts.GetContent() event,
     * which means that when the user selects an image from their gallery,
     * its callback will be invoked
     */
    private val selectImage =
        registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
            viewModel.originImgUri = uri
        }

    /**
     * when there is new content available, it can update the UI with what was selected.
     */
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel.context = this
        setContent {
            EmojilizerTheme() {
                EmojilizerApp()
            }
        }
    }

    @Composable
    private fun EmojilizerApp() {
        val scaffoldState = rememberScaffoldState()
        val scope = rememberCoroutineScope()
        val hintUser: (String) -> Unit = {
            scope.launch {
                scaffoldState.snackbarHostState.showSnackbar(it)
            }
        }
        HomeScreen(
            fetchResponse = { viewModel.fetchResponse(hintUser) },
            selectImage = { selectImage.launch("image/*") },
            saveToGallery = { viewModel.resultImgUri?.let { downloadImageNew(it, hintUser) } },
            invalidateResult = { viewModel.invalidateResultUrl() },
            originImgUri = viewModel.originImgUri,
            resultImgUri = viewModel.resultImgUri,
            scaffoldState = scaffoldState,
        )
    }

    /**
     * download images in background threads using Kotlin Coroutine
     */
    private fun downloadImageNew(downloadUri: Uri, hintUser: (String) -> Unit) {
        // val context = applicationContext
        CoroutineScope(Job() + Dispatchers.IO).launch {
            try {
                val currentMoment: Instant = Clock.System.now()
                val moment: LocalDateTime = currentMoment
                    .toLocalDateTime(currentSystemDefault())
                val filename = "${moment.date}-${moment.hour}${moment.minute}${moment.second}"
                Log.d(TAG, "downloadImageNew: $filename")

                val dm = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
                // val downloadUri: Uri = Uri.parse(downloadUrlOfImage)
                val request = DownloadManager.Request(downloadUri)
                request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
                    .setAllowedOverRoaming(false)
                    .setTitle(filename)
                    .setMimeType("image/jpeg") // Your file type. You can use this code to download other file types also.
                    .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                    .setDestinationInExternalPublicDir(
                        Environment.DIRECTORY_PICTURES,
                        File.separator.toString() + filename + ".jpg"
                    )
                dm.enqueue(request)
                hintUser(getString(R.string.download_begins))
            } catch (e: Exception) {
                e.printStackTrace()
                hintUser(getString(R.string.download_failed))
            }
        }
    }
}